package com.cxyd.modules.wms.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cxyd.common.Utils.BeanUtils;
import com.cxyd.common.constant.Constant;
import com.cxyd.common.constant.enums.wms.*;
import com.cxyd.common.exception.RootException;
import com.cxyd.common.interceptor.UniqueCodeGenerator;
import com.cxyd.common.page.PageData;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.common.utils.ConvertUtils;
import com.cxyd.common.utils.ProcResult;
import com.cxyd.common.utils.Result;
import com.cxyd.modules.api.dao.RmsNoticeDao;
import com.cxyd.modules.api.dto.StockDetailDTO;
import com.cxyd.modules.api.dto.request.TaskRequest;
import com.cxyd.modules.api.entity.RmsNoticeEntity;
import com.cxyd.modules.api.entity.StockDetailEntity;
import com.cxyd.modules.job.utils.RandomStringGenerator;
import com.cxyd.modules.sys.dto.SysUserDTO;
import com.cxyd.modules.sys.service.SysUserService;
import com.cxyd.modules.wms.dao.*;
import com.cxyd.modules.wms.dto.StockDTO;
import com.cxyd.modules.wms.dto.SupplierDTO;
import com.cxyd.modules.wms.dto.po.LocatePo;
import com.cxyd.modules.wms.dto.po.StockAggregatedPo;
import com.cxyd.modules.wms.dto.po.StockSumPo;
import com.cxyd.modules.wms.entity.*;
import com.cxyd.modules.wms.excel.ImportStockExcel;
import com.cxyd.modules.wms.excel.StockExcel;
import com.cxyd.modules.wms.service.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 库存信息
 *
 * @author g_Cycle gengruyi01@163.com
 * @since 1.0.0 2023-04-27
 */
@Service
public class StockServiceImpl extends CrudServiceImpl<StockDao, StockEntity, StockDTO> implements StockService {

    private static final Logger logger = LoggerFactory.getLogger(StockServiceImpl.class);

    private final StockDao stockDao;
    private final LogWorkService logWorkService;
    private final TaskService taskService;
    private final PostWcsService postWcsService;
    private final SpuDao spuDao;
    private final StationDao stationDao;
    private final LocateDao locateDao;
    private final TaskDao taskDao;
    private final ContainerDao containerDao;
    private final OrderDetailDao orderDetailDao;
    private final CommonService commonService;
    private final RmsNoticeDao rmsNoticeDao;
    private final LocateService locateService;
    private final SpuService spuService;
    private final ZoneService zoneService;

    public StockServiceImpl(StockDao stockDao, LogWorkService logWorkService, TaskService taskService, PostWcsService postWcsService, SpuDao spuDao, StationDao stationDao, LocateDao locateDao, TaskDao taskDao, ContainerDao containerDao, OrderDetailDao orderDetailDao, CommonService commonService, RmsNoticeDao rmsNoticeDao, LocateService locateService, SpuService spuService, ZoneService zoneService) {
        this.stockDao = stockDao;
        this.logWorkService = logWorkService;
        this.taskService = taskService;
        this.postWcsService = postWcsService;
        this.spuDao = spuDao;
        this.stationDao = stationDao;
        this.locateDao = locateDao;
        this.taskDao = taskDao;
        this.containerDao = containerDao;
        this.orderDetailDao = orderDetailDao;
        this.commonService = commonService;
        this.rmsNoticeDao = rmsNoticeDao;
        this.locateService = locateService;
        this.spuService = spuService;
        this.zoneService = zoneService;
    }

    @Override
    public PageData<StockDTO> page(Map<String, Object> params) {
        //1.查询库存信息
        final IPage<StockEntity> page = baseDao.selectViewPage(
                getPage(params, "stock_id", true),
                getWrapper(params)
        );
        return getPageData(page, StockDTO.class);
    }

    @Override
    public QueryWrapper<StockEntity> getWrapper(Map<String, Object> params) {
        //查询条件
        String spuNo = (String) params.get("spuNo");
        String spuName = (String) params.get("spuName");
        String contNo = (String) params.get("contNo");
        String curPosition = (String) params.get("curPosition");
        String positionType = (String) params.get("positionType");
        String stockType = (String) params.get("stock_type");
        String lockSt = (String) params.get("lockSt");

        QueryWrapper<StockEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(positionType), "position_type", positionType);
        wrapper.eq(StringUtils.isNotBlank(stockType), "stock_type", stockType);
        wrapper.eq(StringUtils.isNotBlank(lockSt), "lock_st", lockSt);
        wrapper.like(StringUtils.isNotBlank(contNo), "cont_no", contNo);
        wrapper.like(StringUtils.isNotBlank(spuNo), "spu_no", spuNo);
        wrapper.like(StringUtils.isNotBlank(spuName), "spu_name", spuName);
        wrapper.like(StringUtils.isNotBlank(curPosition), "cur_position", curPosition);

        return wrapper;
    }

    @Override
    public List<StockDetailDTO> stockQuery(Map<String, Object> params) {
        List<StockDetailEntity> entityList = baseDao.queryStockList(params);
        return ConvertUtils.sourceToTarget(entityList, StockDetailDTO.class);
    }

    @Override
    public PageData<StockDTO> checkPage(Map<String, Object> params) {
        //获取盘点列表
        IPage<StockEntity> page = baseDao.selectCheckStockList(
                getPage(params, "stock_id", true),
                getWrapper(params));
        //获取分页对象
        return getPageData(page, StockDTO.class);
    }

    @Override
    public PageData<StockExcel> zonePage(Map<String, Object> params) {
        final String spuNo = (String) params.get("spuNo");
        final String spuName = (String) params.get("spuName");
        final String contNo = (String) params.get("contNo");
        final String curPosition = (String) params.get("curPosition");
        final String positionType = (String) params.get("positionType");
        final String equipName = (String) params.get("equipName");

        final QueryWrapper<StockExcel> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(positionType), "position_type", positionType);
        wrapper.eq(StringUtils.isNotBlank("B"), "stock_type", "B");
        wrapper.like(StringUtils.isNotBlank(contNo), "cont_no", contNo);
        wrapper.like(StringUtils.isNotBlank(spuNo), "spu_no", spuNo);
        wrapper.like(StringUtils.isNotBlank(spuName), "spu_name", spuName);
        wrapper.like(StringUtils.isNotBlank(curPosition), "cur_position", curPosition);
        wrapper.like(StringUtils.isNotBlank(equipName), "p.equip_name", equipName);


        int pageNum = Integer.parseInt(params.get("page").toString());
        int pageSize = Integer.parseInt(params.get("limit").toString());
        Page<StockExcel> pageParam = new Page<>(pageNum, pageSize);

        // 2. 构造分页对象,执行分页查询（调用新增的DAO方法）
        IPage<StockExcel> iPage = baseDao.selectZonePage(pageParam, wrapper);

        // 3. 返回分页结果
        return new PageData<>(iPage.getRecords(), iPage.getTotal());
    }

    @Override
    public void stockDisables(List<Long> ids, Integer status) {
        for (Long stockId : ids) {
            StockEntity stockEntity = baseDao.selectById(stockId);
            if (ObjectUtils.isEmpty(stockEntity)) {
                throw new RootException("库存不存在");
            }
            //前端传入status 0就是禁用货位，传入 1就是解禁货位
            int activeNew;
            if (status == 0) {
                activeNew = 1;
            } else {
                activeNew = 0;
            }
            stockEntity.setLockSt(activeNew);
            baseDao.updateById(stockEntity);
        }
    }

    @Override
    public ProcResult stockFreeze(Map<String, Object> params) {
        //业务逻辑...
        baseDao.procStockFreeze(params);
        final String code = (String) params.get("code");
        final String msg = (String) params.get("msg");
        return new ProcResult().result(code, msg);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void stockCheck(Map<String, Object> params) {
        List<String> stockIds = (List<String>) params.get("stockIds");
        if (stockIds == null) {
            throw new RootException("未选择待盘点库存");
        }

        Long userId = (Long) params.get("userId");
        Date startDate = new Date();
        String comment = "创建盘点任务";
        String code = "0";
        String msg = comment + "成功";
        String work = "StockController.check";
        LogWorkEntity insertLogWork = new LogWorkEntity();
        insertLogWork.setWorkName(comment);
//        insertLogWork.setRelateNo();
        insertLogWork.setWorkProc(work);
        insertLogWork.setCreator(userId);
        insertLogWork.setCreateDate(startDate);

        for (String stockId : stockIds) {
            //生成盘库任务 proc_wms_stock_check
            StockEntity stockEntity = stockDao.selectById(stockId);
            if (ObjectUtils.isEmpty(stockEntity)) {
                msg = "库存[" + stockId + "]在表中不存在!请核查";
                throw new RootException(msg);
            }
            //只有[初始]与[配货中]的单据可进行配货
            String contNo = stockEntity.getContNo();
            if (StatusEnum.USABLE.getCode() != stockEntity.getStockSt()) {
                msg = "托盘[" + contNo + "]的库存状态不允许盘点";
                throw new RootException(msg);
            }
            if (!LocateTypeEnum.HW.getCode().contains(stockEntity.getPositionType())) {
                msg = "托盘[" + contNo + "]当前所在位置[" + stockEntity.getCurPosition() + "]不允许盘点";
                throw new RootException(msg);
            }
            StockEntity updateStock = new StockEntity();
            updateStock.setStockSt(StatusEnum.DISABLE.getCode());
            updateStock.setStockId(Long.parseLong(stockId));
            updateStock.setComments(comment);
//        updateStock.setLockedQty(stockEntity.getStockQty());
            updateStock.setUpdater(userId);
            updateStock.setUpdateDate(startDate);
            try {
                stockDao.updateById(updateStock);
            } catch (Exception e) {
                msg = "托盘[" + contNo + "]的库存修改失败";
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(e.getMessage());
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException(msg);
            }
            //业务任务 proc_wms_task_inser
            TaskEntity insertTask = new TaskEntity();
            insertTask.setTaskType(TaskTypeEnum.CHECK.getCode());
            insertTask.setTaskSubType(TaskSubTypeEnum.STOCK_CHECK.getCode());
            insertTask.setContNo(contNo);
            insertTask.setSpuNo(stockEntity.getSpuNo());
            insertTask.setPlanQty(stockEntity.getStockQty());
            insertTask.setActlQty(BigDecimal.ZERO);
            insertTask.setFromPosition(stockEntity.getCurPosition());
            insertTask.setCurrentPosition(stockEntity.getCurPosition());
            insertTask.setStockId(Long.parseLong(stockId));
            insertTask.setTaskSt(TaskStEnum.INITIAL.getCode());
            insertTask.setCreator(userId);
            insertTask.setCreateDate(startDate);
            insertTask.setUpdater(userId);
            insertTask.setUpdateDate(startDate);
            insertTask.setComments(comment);
            try {
                taskService.taskInsert(insertTask);
            } catch (RootException e) {
                msg = "托盘[" + contNo + "]的库存修改失败";
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(e.getMessage());
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException(msg);
            }
        }

        //记录日志
        insertLogWork.setWorkCode(code);
        insertLogWork.setWorkMsg(msg);
        logWorkService.logWorkInsert(insertLogWork);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Result checkAffirm(TaskRequest request) {
        Long taskId = request.getTaskId();
        Integer actlQty = request.getActlQty();
        Long userId = 1004L;
        Date startDate = new Date();
        String comment = "盘点确认";
        String code = "0";
        String msg = comment + "成功";
        String work = "TaskServiceImpl.checkAffirm";
        LogWorkEntity insertLogWork = new LogWorkEntity();
        insertLogWork.setWorkName(comment);
//        insertLogWork.setRelateNo(detailId.toString());
        insertLogWork.setWorkProc(work);
        insertLogWork.setCreator(userId);
        insertLogWork.setCreateDate(startDate);

        TaskEntity taskEntity = taskDao.selectById(taskId);
        if (ObjectUtils.isEmpty(taskEntity) || TaskStEnum.PROGRESS.getCode() != taskEntity.getTaskSt()) {
            msg = "任务[" + taskId + "]不存在或已盘点完成！";
            throw new RootException(msg);
        }
        if (!TaskSubTypeEnum.STOCK_CHECK.getCode().equals(taskEntity.getTaskSubType())) {
            msg = "任务[" + taskId + "]非盘点任务!不可对其盘点";
            throw new RootException(msg);
        }
        Long stockId = taskEntity.getStockId();
        StockEntity stockEntity = stockDao.selectById(stockId);
        if (ObjectUtils.isEmpty(stockEntity)) {
            msg = "库存[" + stockId + "]不存在或无法操作！";
            throw new RootException(msg);
        }
        String curPosition = stockEntity.getCurPosition();
        LocateEntity locateEntity = locateDao.selectOne(new QueryWrapper<LocateEntity>().eq("locate_no", curPosition));
        if (ObjectUtils.isEmpty(locateEntity) || !LocateTypeEnum.OT_ST.getCode().equals(locateEntity.getLocateType())) {
            msg = "托盘[" + taskEntity.getContNo() + "]尚未到达出库站台!请等待";
            throw new RootException(msg);
        }
//        ContainerEntity containerEntity = containerDao.selectOne(new QueryWrapper<ContainerEntity>().eq("cont_no", taskEntity.getContNo()));
//        if (ObjectUtils.isEmpty(containerEntity) || StatusEnum.USABLE.getCode() != containerEntity.getStatus()) {
//            throw new RootException("托盘不存在或者不可用!");
//        }
//        RmsNoticeEntity rmsNoticeEntity = rmsNoticeDao.selectOne(new QueryWrapper<RmsNoticeEntity>().eq("cont_no", containerEntity.getContNo()));
//        if (ObjectUtils.isEmpty(rmsNoticeEntity) && ContTypeEnum.YF.getCode().equals(containerEntity.getContType()) && actlQty != 0) {
//            throw new RootException("请先完成高度检测！");
//        }
//        根据到达的站台就可知其对应设备
        String dvcNo = locateEntity.getDvcNo();
        //修改task
        TaskEntity updateTask = new TaskEntity();
        updateTask.setTaskId(taskId);
        updateTask.setActlQty(new BigDecimal(actlQty));
        updateTask.setTaskSt(TaskStEnum.COMPLETE.getCode());
        updateTask.setUpdater(userId);
        updateTask.setUpdateDate(startDate);
        updateTask.setComments(comment);
        try {
            taskDao.updateById(updateTask);
        } catch (Exception e) {
            logger.info("修改任务失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("修改任务失败！");
        }
        //库存修正
        StockEntity updateStock = new StockEntity();
        String contNo = stockEntity.getContNo();
        //如果盘点库存剩余数量为 0的话，那么就直接删掉
        if (actlQty == 0) {
            baseDao.deleteById(stockId);
            //如果库存不存在，那么就不生成回库任务直接返回
            List<StockEntity> stockEntities = stockDao.selectList(new QueryWrapper<StockEntity>().eq("cont_no", contNo));
            if (ObjectUtils.isEmpty(stockEntities)) {
                return new Result().ok("盘点确认成功!此料箱库存已清空，请执行空托盘入库！");
            }
        } else {
            updateStock.setStockId(stockId);
            updateStock.setStockQty(new BigDecimal(actlQty));
            updateStock.setLockedQty(BigDecimal.ZERO);
            updateStock.setUpdater(userId);
            updateStock.setUpdateDate(startDate);
            updateStock.setComments("原库存数量" + stockEntity.getStockQty() + "盘点确认库存" + actlQty);
            try {
                stockDao.updateById(updateStock);
            } catch (Exception e) {
                logger.info("修改库存失败", e);
                code = "1001";
                msg = e.getMessage();
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException("修改任务失败！");
            }
        }
//        根据设备编号及站台类型（IN）匹配盘点回库的入库站台
        StationEntity stationEntity = stationDao.selectOne(new QueryWrapper<StationEntity>()
                .eq("dvc_no", dvcNo)
                .eq("station_type", "IN"));
        //任务全部执行完成，开始占用货位，生成任务和设备任务
        List<TaskEntity> taskEntityList = taskDao.selectList(new QueryWrapper<TaskEntity>()
                .eq("cont_no", contNo)
                .eq("task_sub_type", TaskSubTypeEnum.STOCK_CHECK.getCode())
                .eq("task_st", TaskStEnum.PROGRESS.getCode()));
        if (CollectionUtils.isEmpty(taskEntityList)) {
            LocateEntity preAllocation;
            try {
                preAllocation = locateService.locatePreAllocation(LocateTypeEnum.CP_HW.getCode(),contNo, "HK", startDate, userId, comment);
            } catch (Exception e) {
                logger.info("货位预占用失败", e);
                code = "1001";
                msg = e.getMessage();
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException("货位预占用失败！");
            }
            //生成任务
            TaskEntity insertTask = new TaskEntity();
            insertTask.setTaskType(TaskTypeEnum.CHECK.getCode());
            insertTask.setTaskSubType(TaskSubTypeEnum.STOCK_RETURN.getCode());
            insertTask.setContNo(stockEntity.getContNo());
//            从回库站台进行盘点回库
            insertTask.setFromPosition(stationEntity.getStationNo());
            insertTask.setCurrentPosition(stationEntity.getStationNo());
            insertTask.setToPosition(preAllocation.getLocateNo());
//            关联库存
            insertTask.setStockId(stockId);
            insertTask.setSpuNo(stockEntity.getSpuNo());
            insertTask.setPlanQty(new BigDecimal(actlQty));
            insertTask.setActlQty(new BigDecimal(actlQty));
            insertTask.setComments(comment);
            insertTask.setCreator(userId);
            insertTask.setCreateDate(startDate);
            insertTask.setUpdater(userId);
            insertTask.setUpdateDate(startDate);
            try {
                taskService.taskInsert(insertTask);
            } catch (Exception e) {
                logger.info("生成任务失败", e);
                code = "1001";
                msg = e.getMessage();
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException("生成任务失败！");
            }
            //生成搬送任务
            PostWcsEntity insertPostWcs = new PostWcsEntity();
            insertPostWcs.setContNo(contNo);
            insertPostWcs.setTrkType(PostWcsTypeEnum.IN.getCode());
            insertPostWcs.setFrmPos(stationEntity.getStationNo());
            insertPostWcs.setCurPos(stationEntity.getStationNo());
            insertPostWcs.setToPos(preAllocation.getLocateNo());
            insertPostWcs.setTrkSt(PostWcsStEnum.INITIAL.getCode());
            insertPostWcs.setIsFull(PostWcsFullEnum.FULL.getCode());
            insertPostWcs.setCreator(userId);
            insertPostWcs.setCreateDate(startDate);
            insertPostWcs.setUpdater(userId);
            insertPostWcs.setUpdateDate(startDate);
            insertPostWcs.setComments(comment);
            postWcsService.postWcsInsert(insertPostWcs);
        }
        //记录日志 proc_wms_log_insert
        msg = "盘点确认成功!实物数量[" + request.getActlQty() + "]";
        insertLogWork.setWorkCode(code);
        insertLogWork.setWorkMsg(msg);
        logWorkService.logWorkInsert(insertLogWork);
        return new Result().ok(msg);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void mergeCall(Map<String, Object> params) {
        Long stockId = Long.parseLong(params.get("stockId").toString());
        String stationNo = (String) params.get("stationNo");
        //合并出库呼叫 proc_wms_merge_call
        String code = "0";
        String msg = "物料合并托盘呼叫成功";
        Date startDate = new Date();
        //是否生成搬送指令 0-无 1-有
        Long userId = (Long) params.get("userId");
        StationEntity stationEntity = stationDao.selectOne(new QueryWrapper<StationEntity>().eq("station_no", stationNo));
        if (ObjectUtils.isEmpty(stationEntity) || stationEntity.getStationSt() != 0) {
            throw new RootException("没有维护此站台或当前站台不可用！");
        }
        StockEntity stockEntity = stockDao.selectById(stockId);
        if (ObjectUtils.isEmpty(stockEntity)) {
            msg = "库存[" + stockId + "]在系统中不存在!";
            throw new RootException(msg);
        }
        String contNo = stockEntity.getContNo();
        if (!"HW".equals(stockEntity.getPositionType())) {
            msg = "托盘[" + contNo + "]不在库内!无法呼出";
            throw new RootException(msg);
        }
        ContainerEntity containerEntity = containerDao.selectOne(new QueryWrapper<ContainerEntity>().eq("cont_no", contNo));
        if (ObjectUtils.isEmpty(containerEntity) || containerEntity.getStatus() != StatusEnum.USABLE.getCode()) {
            throw new RootException("没有维护此托盘或不可用！");
        }
        List<StockEntity> stockEntities = stockDao.selectList(new QueryWrapper<StockEntity>().eq("cont_no", contNo).eq("stock_st", StatusEnum.DISABLE.getCode()));
        if (!CollectionUtils.isEmpty(stockEntities)) {
            throw new RootException("托盘已被使用！");
        }

        String comment = "物料合并";
        String work = "StockController.mergeCall";
        LogWorkEntity insertLogWork = new LogWorkEntity();
        insertLogWork.setWorkName(comment);
        insertLogWork.setWorkProc(work);
        insertLogWork.setCreator(userId);
        insertLogWork.setCreateDate(startDate);

        StockEntity updateStock = new StockEntity();
        updateStock.setStockSt(StatusEnum.DISABLE.getCode());
        updateStock.setUpdateDate(startDate);
        updateStock.setUpdater(userId);
        updateStock.setComments(comment);
        try {
            stockDao.update(updateStock, new UpdateWrapper<StockEntity>().eq("cont_no", contNo));
        } catch (RootException e) {
            logger.info("修改库存状态异常!", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setRelateNo(contNo);
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException(1001, "修改库存状态异常!");
        }

        //生成任务 proc_wms_task_insert
        TaskEntity insertTask = new TaskEntity();
        insertTask.setTaskType(TaskTypeEnum.OUTBOUND.getCode());
        insertTask.setTaskSubType(TaskSubTypeEnum.STOCK_MERGE.getCode());
        insertTask.setContNo(contNo);
        insertTask.setSpuNo(stockEntity.getSpuNo());
        insertTask.setPlanQty(stockEntity.getStockQty());
        insertTask.setActlQty(stockEntity.getStockQty());
        insertTask.setFromPosition(stockEntity.getCurPosition());
        insertTask.setToPosition(stationNo);
        insertTask.setCurrentPosition(stockEntity.getCurPosition());
        insertTask.setStockId(stockId);
        insertTask.setCreator(userId);
        try {
            taskService.taskInsert(insertTask);
        } catch (RootException e) {
            logger.info("生成[task]异常!", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setRelateNo(contNo);
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException(1001, "生成[task]异常!");
        }
        //搬送指令 proc_wms_post_wcs_insert
        PostWcsEntity insertPostWcs = new PostWcsEntity();
        insertPostWcs.setContNo(contNo);
        insertPostWcs.setContType(containerEntity.getContType());
        insertPostWcs.setTrkType(PostWcsTypeEnum.OT.getCode());
        insertPostWcs.setFrmPos(insertTask.getCurrentPosition());
        insertPostWcs.setToPos(stationNo);
        insertPostWcs.setCurPos(insertTask.getCurrentPosition());
        insertPostWcs.setIsFull(PostWcsFullEnum.FULL.getCode());
        insertPostWcs.setCreator(userId);
        insertPostWcs.setCreateDate(startDate);
        insertPostWcs.setUpdater(userId);
        insertPostWcs.setUpdateDate(startDate);
        insertPostWcs.setComments(comment);
        try {
            postWcsService.postWcsInsert(insertPostWcs);
            msg = "'托盘[" + contNo + "]被呼出用于合料!目标站台[" + stationNo + "]";
        } catch (Exception e) {
            logger.info("生成[post]异常!", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setRelateNo(contNo);
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException(1001, "生成[post]异常!");
        }
        //记录日志
        insertLogWork.setWorkCode(code);
        insertLogWork.setWorkMsg(msg);
        insertLogWork.setRelateNo(stationNo + "-" + contNo);
        logWorkService.logWorkInsert(insertLogWork);
    }

    public void stockInsert(StockEntity stockEntity) {
        String code = "0";
        String msg = "";
        Date startDate = new Date();
        String spuNo = stockEntity.getSpuNo();
        QueryWrapper<SpuEntity> spuQuery = new QueryWrapper<>();
        spuQuery.eq("spu_no", spuNo);
        List<SpuEntity> spuEntities = spuDao.selectList(spuQuery);
        String spuName;
        if (CollectionUtils.isEmpty(spuEntities)) {
            spuName = "未知物料";
        } else {
            spuName = spuEntities.get(0).getSpuName();
        }
        stockEntity.setSpuName(spuName);
        stockEntity.setStockSt(0);
        try {
            stockDao.insert(stockEntity);
            msg = "数据写入成功";
        } catch (Exception e) {
            logger.info("stockInsert异常!", e);
            msg = "stockInsert异常";
            throw new RootException(1006, msg);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void outbound(Map<String, Object> params) {
        Long taskId = (Long) params.get("taskId");
        Long userId = (Long) params.get("userId");
        String code = "0";
        String comment = "盘点出库";
        String msg = comment + "成功";
        TaskEntity taskEntity = taskService.selectById(taskId);
        if (ObjectUtils.isEmpty(taskEntity)) {
            msg = "任务[" + taskId + "]不存在!";
            throw new RootException(msg);
        }
        if (TaskStEnum.INITIAL.getCode() != taskEntity.getTaskSt()) {
            msg = "任务[" + taskId + "]已执行!";
            throw new RootException(msg);
        }
        //初始化参数
        Date startDate = new Date();
        String work = "StockController.outbound";
        LogWorkEntity insertLogWork = new LogWorkEntity();
        insertLogWork.setWorkName(comment);
        insertLogWork.setWorkProc(work);
        insertLogWork.setCreator(userId);
        insertLogWork.setCreateDate(startDate);
//        根据料箱获取出库站台信息
        ContainerEntity containerEntity = containerDao.selectOne(new QueryWrapper<ContainerEntity>().eq("cont_no", taskEntity.getContNo()));
        String dvcNo = containerEntity.getContType();
        //查询站台
        List<StationEntity> stationEntities = stationDao.selectList(new QueryWrapper<StationEntity>()
                .eq("dvc_no", dvcNo)
                .eq("station_type", "OT")
                .eq("station_st", StatusEnum.USABLE.getCode()));
        if (CollectionUtils.isEmpty(stationEntities)) {
            msg = "当前无可用出库站台!任务[" + taskId + "]!";
            throw new RootException(msg);
        }
        StationEntity stationEntity = stationEntities.get(0);
        //修改task状态
        TaskEntity updateTask = new TaskEntity();
        updateTask.setTaskSt(TaskStEnum.PROGRESS.getCode());
        updateTask.setToPosition(stationEntity.getStationNo());
        updateTask.setUpdater(userId);
        updateTask.setUpdateDate(startDate);
        updateTask.setComments(comment);
        taskService.update(updateTask, new UpdateWrapper<TaskEntity>()
                .eq("cont_no", taskEntity.getContNo())
                .eq("task_sub_type", TaskSubTypeEnum.STOCK_CHECK.getCode())
                .eq("task_st", TaskStEnum.INITIAL.getCode()));
        //生成设备任务
        PostWcsEntity insertPostWcs = new PostWcsEntity();
        insertPostWcs.setContNo(taskEntity.getContNo());
        insertPostWcs.setTrkType(PostWcsTypeEnum.OT.getCode());
        insertPostWcs.setFrmPos(taskEntity.getFromPosition());
        insertPostWcs.setToPos(stationEntity.getStationNo());
        insertPostWcs.setCurPos(taskEntity.getCurrentPosition());
        insertPostWcs.setIsFull(PostWcsFullEnum.FULL.getCode());
        insertPostWcs.setTrkSt(PostWcsStEnum.INITIAL.getCode());
        insertPostWcs.setCreator(userId);
        insertPostWcs.setCreateDate(startDate);
        insertPostWcs.setUpdater(userId);
        insertPostWcs.setUpdateDate(startDate);
        insertPostWcs.setComments(comment);
        try {
            postWcsService.postWcsInsert(insertPostWcs);
        } catch (Exception e) {
            msg = "生成设备任务失败!任务[" + taskId + "]!";
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(e.getMessage());
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException(msg);
        }
        //记录日志
        insertLogWork.setWorkCode(code);
        insertLogWork.setWorkMsg(msg);
        logWorkService.logWorkInsert(insertLogWork);
    }

    @Override
    public void cancel(Map<String, Object> params) {
        Long taskId = (Long) params.get("taskId");
        Long userId = (Long) params.get("userId");
        Date startDate = new Date();
        String comment = "取消盘点任务";
        String code = "0";
        String msg = comment + "成功";
        String work = "StockController.cancel";
        LogWorkEntity insertLogWork = new LogWorkEntity();
        insertLogWork.setWorkName(comment);
//        insertLogWork.setRelateNo();
        insertLogWork.setWorkProc(work);
        insertLogWork.setCreator(userId);
        insertLogWork.setCreateDate(startDate);
        TaskEntity taskEntity = taskService.selectById(taskId);
        if (TaskStEnum.INITIAL.getCode() != taskEntity.getTaskSt()) {
            msg = "任务[" + taskId + "]无法取消！";
            throw new RootException(msg);
        }
        //取消盘点时需将库存的预分配状态清掉
        TaskEntity task = taskService.selectById(taskId);
        List<StockEntity> stockEntities = this.selectByCurPosition(task.getFromPosition());
        for (StockEntity stockEntity : stockEntities) {
            if (ObjectUtils.isNotEmpty(stockEntity) && stockEntity.getPositionType().equals("HW")) {
                stockEntity.setStockSt(0);
                baseDao.updateById(stockEntity);
            }
        }
        TaskEntity updateTask = new TaskEntity();
        updateTask.setTaskId(taskId);
        updateTask.setTaskSt(TaskStEnum.CANCEL.getCode());
        updateTask.setUpdater(userId);
        updateTask.setUpdateDate(startDate);
        updateTask.setComments(comment);
        taskService.updateById(updateTask);
        //记录日志
        insertLogWork.setWorkCode(code);
        insertLogWork.setWorkMsg(msg);
        logWorkService.logWorkInsert(insertLogWork);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Result outboundCompleted(TaskRequest request) {
        String contNo = UniqueCodeGenerator.generateCode();
        Integer actlQty = request.getActlQty();
//        Long taskId = request.getTaskId();
//        TaskEntity taskEntity = taskDao.selectById(taskId);
//        if (ObjectUtils.isEmpty(taskEntity) || TaskStEnum.PROGRESS.getCode() != taskEntity.getTaskSt()) {
//            throw new RootException("没有正在执行的托盘任务");
//        }
//        if (actlQty != taskEntity.getPlanQty().intValue()) {
//            throw new RootException("领料数量必须等于计划数量！");
//        }

//        if (!taskEntity.getSpuNo().equals(request.getSpuNo())) {
//            throw new RootException("领取物料和任务物料不一致！");
//        }
        Date startDate = new Date();
        String code = "0";
        String msg = "出库确认";
        String comment = "出库确认";
        String work = "RfController.outboundCompleted";
        Long userId = Constant.ClientCode.PDA.getId();
        LogWorkEntity insertLogWork = new LogWorkEntity();
        insertLogWork.setWorkName(comment);
        insertLogWork.setRelateNo(contNo);
        insertLogWork.setWorkProc(work);
        insertLogWork.setCreator(userId);
        insertLogWork.setCreateDate(startDate);
//        try {
//            taskDao.update(null, new UpdateWrapper<TaskEntity>().eq("task_id", taskId)
//                    .set("actl_qty", new BigDecimal(actlQty))
//                    .set("task_st", TaskStEnum.COMPLETE.getCode())
//                    .set("updater", userId).set("update_date", startDate));
//        } catch (Exception e) {
//            logger.info("修改任务失败", e);
//            code = "1001";
//            msg = e.getMessage();
//            insertLogWork.setRelateNo(contNo);
//            insertLogWork.setWorkCode(code);
//            insertLogWork.setWorkMsg(msg);
//            logWorkService.logWorkInsert(insertLogWork);
//            throw new RootException("修改任务失败！");
//        }
        Long stockId = request.getStockId();
        StockEntity stockEntity = stockDao.selectById(stockId);
        BigDecimal stockQty = stockEntity.getStockQty().subtract(new BigDecimal(actlQty));
//        BigDecimal lockedQty = stockEntity.getLockedQty().subtract(new BigDecimal(actlQty));
        if (BigDecimal.ZERO.compareTo(stockQty) > 0) {
            throw new RootException("库存不足！");
        }
        try {
            if (BigDecimal.ZERO.compareTo(stockQty) == 0) {
                stockDao.deleteById(stockId);
            } else {
                stockDao.update(null, new UpdateWrapper<StockEntity>().eq("stock_id", stockId)
                        .set("stock_qty", stockQty)
//                        .set("locked_qty", lockedQty)
                        .set("updater", userId).set("update_date", startDate));
            }
        } catch (Exception e) {
            logger.info("修改库存失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setRelateNo(contNo);
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("修改库存失败！");
        }
        //订单状态
//        List<Integer> taskStList = new ArrayList<>();
//        taskStList.add(TaskStEnum.PROGRESS.getCode());
//        taskStList.add(TaskStEnum.INITIAL.getCode());
//        List<TaskEntity> list = taskDao.selectList(new QueryWrapper<TaskEntity>()
//                .eq("detail_id", taskEntity.getDetailId()).in("task_st", taskStList));
//        if (CollectionUtils.isEmpty(list)) {
//            OrderDetailEntity updateOrderDetail = orderDetailDao.selectById(taskEntity.getDetailId());
//            //出库实际需要累加-更新日期2025年4月15日
//            BigDecimal curActlQty = updateOrderDetail.getActlQty().add(new BigDecimal(actlQty));
//            updateOrderDetail.setActlQty(curActlQty);
//            updateOrderDetail.setDetailSt(OrderStatusEnum.OUT_COMPLETE.getCode());
//            updateOrderDetail.setUpdater(userId);
//            updateOrderDetail.setUpdateDate(startDate);
//            updateOrderDetail.setComments(comment);
//            try {
//                orderDetailDao.updateById(updateOrderDetail);
//            } catch (Exception e) {
//                logger.info("修改出库明细失败", e);
//                code = "1001";
//                msg = e.getMessage();
//                insertLogWork.setWorkCode(code);
//                insertLogWork.setWorkMsg(msg);
//                logWorkService.logWorkInsert(insertLogWork);
//                throw new RootException("修改出库明细失败！");
//            }
//            //修改主单状态
//            Map<String, Object> params = new HashMap<>();
//            params.put("orderId", taskEntity.getMtId());
//            params.put("comment", comment);
//            params.put("userId", userId);
//            try {
//                commonService.orderStatus(params);
//            } catch (Exception e) {
//                logger.info("修改主单失败", e);
//                code = "1001";
//                msg = e.getMessage();
//                insertLogWork.setWorkCode(code);
//                insertLogWork.setWorkMsg(msg);
//                logWorkService.logWorkInsert(insertLogWork);
//                throw new RootException("修改主单失败！");
//            }
//        }
//        List<TaskEntity> taskEntityList = taskDao.selectList(new QueryWrapper<TaskEntity>().eq("cont_no", contNo).eq("task_st", TaskStEnum.PROGRESS.getCode()));
//        if (!CollectionUtils.isEmpty(taskEntityList)) {
//            return new Result().ok("物料并未领完，请继续领料！");
//        }
//        List<StockEntity> stockEntities = stockDao.selectList(new QueryWrapper<StockEntity>().eq("cont_no", contNo));
//        if (CollectionUtils.isEmpty(stockEntities)) {
//            return new Result().ok("托盘物料已领完，请执行空托盘入库！");
//        }
        StockEntity stockEntity1 = stockDao.selectOne(new QueryWrapper<StockEntity>().eq("stock_id", stockId));
        if (ObjectUtils.isEmpty(stockEntity1)) {
            return new Result().ok("物料领取成功！");
        }
//        ContainerEntity containerEntity = containerDao.selectOne(new QueryWrapper<ContainerEntity>().eq("cont_no", contNo));

        List<LocateEntity> locateEntities;
        //如果是海康的托盘就分配海康的货位
//        if (containerEntity.getContType().equals(ContTypeEnum.HK.getCode())) {
            locateEntities = locateDao.selectList(new QueryWrapper<LocateEntity>()
                    .eq("locate_st", LocateStEnum.FREE.getCode())
                    .eq("active", StatusEnum.USABLE.getCode())
                    .eq("locate_type", LocateTypeEnum.CP_HW.getCode())
                    .eq("dvc_No", ContTypeEnum.HK.getCode())
                    .orderByAsc("level_num", "col_num", "row_num"));
//        }
//        else {
//            locateEntities = locateDao.selectList(new QueryWrapper<LocateEntity>()
//                    .eq("locate_st", LocateStEnum.FREE.getCode())
//                    .eq("active", StatusEnum.USABLE.getCode())
//                    .eq("locate_type", LocateTypeEnum.HW.getCode())
//                    .eq("dvc_No", ContTypeEnum.YF.getCode())
//                    .orderByAsc("level_num", "col_num", "row_num"));
//        }

        if (CollectionUtils.isEmpty(locateEntities)) {
            throw new RootException("没有空闲的货位！");
        }
        //货位预分配
        LocateEntity locateEntity = locateEntities.get(0);
        LocatePo updateLocate = new LocatePo();
        updateLocate.setLocateId(locateEntity.getLocateId());
        updateLocate.setLocateSt(LocateStEnum.PRE.getCode());
        updateLocate.setLocateStOld(LocateStEnum.FREE.getCode());
        updateLocate.setContNo(contNo);
        updateLocate.setUpdateDate(startDate);
        updateLocate.setUpdater(userId);
        updateLocate.setComments(comment);
        try {
            int locateUpdateNum = locateDao.occupy(updateLocate);
            if (locateUpdateNum <= 0) {
                throw new RootException("货位预占用失败！");
            }
        } catch (Exception e) {
            logger.info("货位预占用失败，货位号={}", locateEntity.getLocateNo(), e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("货位预占用失败！");
        }
//        StockEntity stockEntity1 = stockEntities.get(0);
        TaskEntity insertTask = new TaskEntity();
        insertTask.setTaskType(TaskTypeEnum.WAREHOUSE_ENTRY.getCode());
        insertTask.setTaskSubType(TaskSubTypeEnum.SURPLUS_RETURN.getCode());
        insertTask.setContNo(contNo);
        insertTask.setPlanQty(BigDecimal.ZERO);
        insertTask.setActlQty(BigDecimal.ZERO);
//        根据容器所属库区的回库站台
        LocateEntity locateEntity1 = locateDao.selectOne(new QueryWrapper<LocateEntity>().lambda().eq(LocateEntity::getDvcNo, locateEntity.getDvcNo())
                .eq(LocateEntity::getLocateType, LocateTypeEnum.IN_ST.getCode())
                .eq(LocateEntity::getLocateSt, LocateStEnum.FREE.getCode())
                .eq(LocateEntity::getActive, StatusEnum.USABLE.getCode()).last("limit 1"));
        //起点货位预分配
        LocatePo updateLocate1 = new LocatePo();
        updateLocate1.setLocateId(locateEntity1.getLocateId());
        updateLocate1.setLocateSt(LocateStEnum.PRE.getCode());
        updateLocate1.setLocateStOld(LocateStEnum.FREE.getCode());
        updateLocate1.setContNo(contNo);
        updateLocate1.setUpdateDate(startDate);
        updateLocate1.setUpdater(userId);
        updateLocate1.setComments(comment);
        try {
            int locateUpdateNum = locateDao.occupy(updateLocate1);
            if (locateUpdateNum <= 0) {
                throw new RootException("货位预占用失败！");
            }
        } catch (Exception e) {
            logger.info("货位预占用失败，货位号={}", locateEntity1.getLocateNo(), e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("货位预占用失败！");
        }
        String fromPosition = locateEntity1.getLocateNo();

        insertTask.setFromPosition(fromPosition);
        insertTask.setToPosition(locateEntity.getLocateNo());
        insertTask.setCurrentPosition(fromPosition);
        insertTask.setTaskSt(TaskStEnum.INITIAL.getCode());
        insertTask.setCreateDate(startDate);
        insertTask.setCreator(userId);
        insertTask.setUpdater(userId);
        insertTask.setUpdateDate(startDate);
        insertTask.setComments(comment);
        insertTask.setSpuNo(stockEntity1.getSpuNo());
        insertTask.setSpuName(stockEntity1.getSpuName());
        insertTask.setPlanQty(stockEntity1.getStockQty());
        insertTask.setActlQty(stockEntity1.getStockQty());
        insertTask.setStockId(stockEntity1.getStockId());
        try {
            taskService.taskInsert(insertTask);
        } catch (Exception e) {
            logger.info("生成任务失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("生成任务失败！");
        }
        //生成搬送任务
        PostWcsEntity insertPostWcs = new PostWcsEntity();
        insertPostWcs.setContNo(contNo);
        insertPostWcs.setContType("HK");
        insertPostWcs.setTrkType(PostWcsTypeEnum.IN.getCode());
        //起始位置与wms_task保持一致
        insertPostWcs.setFrmPos(fromPosition);
        insertPostWcs.setToPos(locateEntity.getLocateNo());
        insertPostWcs.setCurPos(fromPosition);
        insertPostWcs.setTrkSt(PostWcsStEnum.INITIAL.getCode());
        insertPostWcs.setIsFull(PostWcsFullEnum.EMPTY.getCode());
        insertPostWcs.setCreator(userId);
        insertPostWcs.setCreateDate(startDate);
        insertPostWcs.setUpdater(userId);
        insertPostWcs.setUpdateDate(startDate);
        insertPostWcs.setComments(comment);
        try {
            postWcsService.postWcsInsert(insertPostWcs);
        } catch (Exception e) {
            logger.info("生成搬送任务失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("生成搬送任务失败！");
        }
//        msg = "从容器[" + contNo + "]中领取物料[" + request.getSpuNo() + "]数量[" + actlQty + "]成功!";
        msg = "从站台[" + request.getLocateNo() + "]中领取物料[" + request.getSpuNo() + "]数量[" + actlQty + "]成功!";
        insertLogWork.setWorkCode(code);
        insertLogWork.setWorkMsg(msg);
        logWorkService.logWorkInsert(insertLogWork);
        return new Result().ok(msg);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Result outboundCompletedZero(TaskRequest request) {
        String contNo = request.getContNo();
        Integer actlQty = request.getActlQty();
        Long taskId = request.getTaskId();
        TaskEntity taskEntity = taskDao.selectById(taskId);
        if (ObjectUtils.isEmpty(taskEntity) || TaskStEnum.PROGRESS.getCode() != taskEntity.getTaskSt()) {
            throw new RootException("没有正在执行的托盘任务");
        }
        if (!taskEntity.getSpuNo().equals(request.getSpuNo())) {
            throw new RootException("领取物料和任务物料不一致！");
        }
        Date startDate = new Date();
        String code = "0";
        String msg = "出库确认";
        String comment = "出库0确认";
        String work = "RfController.outboundCompletedZero";
        Long userId = Constant.ClientCode.PDA.getId();
        LogWorkEntity insertLogWork = new LogWorkEntity();
        insertLogWork.setWorkName(comment);
        insertLogWork.setRelateNo(contNo);
        insertLogWork.setWorkProc(work);
        insertLogWork.setCreator(userId);
        insertLogWork.setCreateDate(startDate);
        try {
            taskDao.update(null, new UpdateWrapper<TaskEntity>().eq("task_id", taskId)
                    .set("actl_qty", new BigDecimal(actlQty))
                    .set("task_st", TaskStEnum.COMPLETE.getCode())
                    .set("updater", userId).set("update_date", startDate));
        } catch (Exception e) {
            logger.info("修改任务失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setRelateNo(contNo);
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("修改任务失败！");
        }

        //订单状态
        List<Integer> taskStList = new ArrayList<>();
        taskStList.add(TaskStEnum.PROGRESS.getCode());
        taskStList.add(TaskStEnum.INITIAL.getCode());
        List<TaskEntity> list = taskDao.selectList(new QueryWrapper<TaskEntity>()
                .eq("detail_id", taskEntity.getDetailId()).in("task_st", taskStList));
        if (CollectionUtils.isEmpty(list)) {
            OrderDetailEntity updateOrderDetail = orderDetailDao.selectById(taskEntity.getDetailId());
            //出库0确认时，无需更改实发数量-更新日期2025年4月29日
//            BigDecimal curActlQty = updateOrderDetail.getActlQty().add(new BigDecimal(actlQty));
//            updateOrderDetail.setActlQty(curActlQty);
            updateOrderDetail.setDetailSt(OrderStatusEnum.OUT_COMPLETE.getCode());
            updateOrderDetail.setUpdater(userId);
            updateOrderDetail.setUpdateDate(startDate);
            updateOrderDetail.setComments(comment);
            try {
                orderDetailDao.updateById(updateOrderDetail);
            } catch (Exception e) {
                logger.info("修改出库明细失败", e);
                code = "1001";
                msg = e.getMessage();
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException("修改出库明细失败！");
            }
            //修改主单状态
            Map<String, Object> params = new HashMap<>();
            params.put("orderId", taskEntity.getMtId());
            params.put("comment", comment);
            params.put("userId", userId);
            try {
                commonService.orderStatus(params);
            } catch (Exception e) {
                logger.info("修改主单失败", e);
                code = "1001";
                msg = e.getMessage();
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException("修改主单失败！");
            }
        }
        List<TaskEntity> taskEntityList = taskDao.selectList(new QueryWrapper<TaskEntity>().eq("cont_no", contNo).eq("task_st", TaskStEnum.PROGRESS.getCode()));
        if (!CollectionUtils.isEmpty(taskEntityList)) {
            return new Result().ok("物料并未领完，请继续领料！");
        }
        List<StockEntity> stockEntities = stockDao.selectList(new QueryWrapper<StockEntity>().eq("cont_no", contNo));
        if (CollectionUtils.isEmpty(stockEntities)) {
            return new Result().ok("托盘物料已领完，请执行空托盘入库！");
        }
        ContainerEntity containerEntity = containerDao.selectOne(new QueryWrapper<ContainerEntity>().eq("cont_no", contNo));

        List<LocateEntity> locateEntities;
        //如果是海康的托盘就分配海康的货位
//        if (containerEntity.getContType().equals(ContTypeEnum.HK.getCode())) {
            locateEntities = locateDao.selectList(new QueryWrapper<LocateEntity>()
                    .eq("locate_st", LocateStEnum.FREE.getCode())
                    .eq("active", StatusEnum.USABLE.getCode())
                    .eq("locate_type", LocateTypeEnum.CP_HW.getCode())
                    .eq("dvc_No", ContTypeEnum.HK.getCode())
                    .orderByAsc("level_num", "col_num", "row_num"));
//        }
//        else {
//            locateEntities = locateDao.selectList(new QueryWrapper<LocateEntity>()
//                    .eq("locate_st", LocateStEnum.FREE.getCode())
//                    .eq("active", StatusEnum.USABLE.getCode())
//                    .eq("locate_type", LocateTypeEnum.HW.getCode())
//                    .eq("dvc_No", ContTypeEnum.YF.getCode())
//                    .orderByAsc("level_num", "col_num", "row_num"));
//        }

        if (CollectionUtils.isEmpty(locateEntities)) {
            throw new RootException("没有空闲的货位！");
        }
        //货位预分配
        LocateEntity locateEntity = locateEntities.get(0);
        LocatePo updateLocate = new LocatePo();
        updateLocate.setLocateId(locateEntity.getLocateId());
        updateLocate.setLocateSt(LocateStEnum.PRE.getCode());
        updateLocate.setLocateStOld(LocateStEnum.FREE.getCode());
        updateLocate.setContNo(contNo);
        updateLocate.setUpdateDate(startDate);
        updateLocate.setUpdater(userId);
        updateLocate.setComments(comment);
        try {
            int locateUpdateNum = locateDao.occupy(updateLocate);
            if (locateUpdateNum <= 0) {
                throw new RootException("货位预占用失败！");
            }
        } catch (Exception e) {
            logger.info("货位预占用失败，货位号={}", locateEntity.getLocateNo(), e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("货位预占用失败！");
        }
        StockEntity stockEntity1 = stockEntities.get(0);
        TaskEntity insertTask = new TaskEntity();
        insertTask.setTaskType(TaskTypeEnum.WAREHOUSE_ENTRY.getCode());
        insertTask.setTaskSubType(TaskSubTypeEnum.SURPLUS_RETURN.getCode());
        insertTask.setContNo(contNo);
        insertTask.setPlanQty(BigDecimal.ZERO);
        insertTask.setActlQty(BigDecimal.ZERO);
//        根据容器所属库区的回库站台
        String fromPosition = "CP_IN_ST";
        if ("GJ".equals(locateEntity.getDvcNo())) {
            fromPosition = "GJ_IN_ST";
        }
        insertTask.setFromPosition(fromPosition);
        insertTask.setToPosition(locateEntity.getLocateNo());
        insertTask.setCurrentPosition(fromPosition);
        insertTask.setTaskSt(TaskStEnum.INITIAL.getCode());
        insertTask.setCreateDate(startDate);
        insertTask.setCreator(userId);
        insertTask.setUpdater(userId);
        insertTask.setUpdateDate(startDate);
        insertTask.setComments(comment);
        insertTask.setSpuNo(stockEntity1.getSpuNo());
        insertTask.setSpuName(stockEntity1.getSpuName());
        insertTask.setPlanQty(stockEntity1.getStockQty());
        insertTask.setActlQty(stockEntity1.getStockQty());
        insertTask.setStockId(stockEntity1.getStockId());
        try {
            taskService.taskInsert(insertTask);
        } catch (Exception e) {
            logger.info("生成任务失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("生成任务失败！");
        }
        //生成搬送任务
        PostWcsEntity insertPostWcs = new PostWcsEntity();
        insertPostWcs.setContNo(contNo);
        insertPostWcs.setContType(containerEntity.getContType());
        insertPostWcs.setTrkType(PostWcsTypeEnum.IN.getCode());
        //起始位置与wms_task保持一致
        insertPostWcs.setFrmPos(fromPosition);
        insertPostWcs.setToPos(locateEntity.getLocateNo());
        insertPostWcs.setCurPos(fromPosition);
        insertPostWcs.setTrkSt(PostWcsStEnum.INITIAL.getCode());
        insertPostWcs.setIsFull(PostWcsFullEnum.EMPTY.getCode());
        insertPostWcs.setCreator(userId);
        insertPostWcs.setCreateDate(startDate);
        insertPostWcs.setUpdater(userId);
        insertPostWcs.setUpdateDate(startDate);
        insertPostWcs.setComments(comment);
        try {
            postWcsService.postWcsInsert(insertPostWcs);
        } catch (Exception e) {
            logger.info("生成搬送任务失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("生成搬送任务失败！");
        }
        msg = "从容器[" + contNo + "]中领取物料[" + request.getSpuNo() + "]数量[" + actlQty + "]成功!";
        insertLogWork.setWorkCode(code);
        insertLogWork.setWorkMsg(msg);
        logWorkService.logWorkInsert(insertLogWork);
        return new Result().ok(msg);
    }

    @Transactional(rollbackFor = Exception.class)
    public int batchSaveOrUpdate(List<ImportStockExcel> list) {
        int count = 0;
        for (ImportStockExcel excel : list) {
            // 1. 数据校验（示例）
            if (excel.getStockQty() == null || excel.getStockQty().compareTo(BigDecimal.ZERO) <= 0) {
                throw new RuntimeException("库存量不能为空或小于0");
            }
            if (StrUtil.isEmpty(excel.getContNo())) {
                throw new RuntimeException("托盘条码不能为空！");
            }
            if (StrUtil.isEmpty(excel.getCurPosition())) {
                throw new RuntimeException("所在位置不能为空！");
            }
            String spuNo = excel.getSpuNo();
            if (StrUtil.isEmpty(excel.getSpuNo())) {
                throw new RuntimeException("物料编号不能为空！");
            }
            SpuEntity spuEntity = spuService.findBySpuNo(spuNo);
            if (ObjectUtils.isEmpty(spuEntity)) {
                throw new RuntimeException("物料信息不存在！请添加物料信息：" + spuNo);
            }
            String zoneNo = excel.getZoneNo();
            ZoneEntity zoneEntity = zoneService.getByZoneNo(zoneNo);
            if (ObjectUtils.isEmpty(zoneEntity)) {
                throw new RootException("区域编号不存在！请添加区域编号：" + zoneNo);
            }
            excel.setSpuName(spuEntity.getSpuName());

            // 2. 转换为实体对象（假设 StockEntity 是数据库实体）
            StockEntity stock = convertToEntity(excel);
            stock.setPositionType("HW");
            stock.setStockType("B");
            // 3. 保存或更新
            if (stock.getStockId() != null) {
                baseDao.updateById(stock);
            } else {
                baseDao.insert(stock);
            }
            count++;
        }
        return count;
    }

    @Override
    public List<StockEntity> selectByCurPosition(String curPosition) {
        QueryWrapper<StockEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(StockEntity::getCurPosition, curPosition);
        return baseDao.selectList(qw);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result errorContAdd(Map<String, Object> map) {
        try {
            if (ObjectUtils.isEmpty(map.get("row_num"))) {
                throw new RootException("排不能为空！");
            }
            map.put("dvc_no", "HK");
            map.put("locate_type", "HW");
            List<LocateEntity> locateEntities = locateService.findByParams(map);
            if (ObjectUtils.isEmpty(locateEntities)) {
                throw new RootException("未找到货架！");
            }
            int count = 0;
            for (LocateEntity locateEntity : locateEntities) {
                if (!locateEntity.getDvcNo().equals("HK")) {
                    throw new RootException("只能生成海康货架的库存！");
                }
                //如果查询到有库存，那么就跳过此货位
                List<StockEntity> stockEntities = this.selectByCurPosition(locateEntity.getLocateNo());
                if (ObjectUtils.isNotEmpty(stockEntities)) {
                    continue;
                }
                StockEntity insertStock = new StockEntity();
                String contNo = RandomStringGenerator.generateRandomString(8);
                insertStock.setCurPosition(locateEntity.getLocateNo());
                insertStock.setContNo(contNo);
                insertStock.setSpuNo("00000000");
                insertStock.setSpuName("空容器");
                insertStock.setPositionType(LocateTypeEnum.GJ_HW.getCode());
                insertStock.setStockQty(new BigDecimal(1));
                insertStock.setStockSt(StatusEnum.USABLE.getCode());
                insertStock.setLockSt(StatusEnum.DISABLE.getCode());
                insertStock.setLockedQty(BigDecimal.ZERO);
                insertStock.setCreator(Constant.ClientCode.WMS.getId());
                insertStock.setCreateDate(new Date());
                insertStock.setComments("人工异常空箱添加");

                baseDao.insert(insertStock);
                count++;
            }
            return new Result().success("空容器库存添加成功！成功数量为：" + count);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result().error("添加失败: " + e.getMessage());
        }
    }

    @Override
    public PageData<StockAggregatedPo> pageBySpuNo(Map<String, Object> params) {
        // 1. 解析分页参数
        int pageNum = Integer.parseInt(params.get("page").toString());
        int pageSize = Integer.parseInt(params.get("limit").toString());
        Page<StockAggregatedPo> pageParam = new Page<>(pageNum, pageSize);

        // 2. 构造分页对象,执行分页查询（调用新增的DAO方法）
        IPage<StockAggregatedPo> iPage = baseDao.selectOrderBySpuNo(pageParam, getWrapperBySpuNo(params));

        // 3. 返回分页结果
        return new PageData<>(iPage.getRecords(), iPage.getTotal());
    }

    @Override
    public PageData<StockSumPo> sumStock(Map<String, Object> params) {
        // 1. 解析分页参数
        int pageNum = Integer.parseInt(params.get("page").toString());
        int pageSize = Integer.parseInt(params.get("limit").toString());
        Page<StockSumPo> pageParam = new Page<>(pageNum, pageSize);
        //获取查询参数
        String spuNo = params.get("spuNo").toString();
        String SpuName = params.get("spuName").toString();
        String equipType = params.get("equipType").toString();
        String drawNo = params.get("drawNo").toString();
        QueryWrapper<StockSumPo> qw = new QueryWrapper<>();
        qw.like(StringUtils.isNotBlank(spuNo), "spu_no", spuNo);
        qw.like(StringUtils.isNotBlank(SpuName), "spu_name", SpuName);
        qw.like(StringUtils.isNotBlank(equipType), "equip_type", equipType);
        qw.like(StringUtils.isNotBlank(drawNo), "draw_no", drawNo);
        IPage<StockSumPo> iPage = baseDao.selectSumStockBySpuNo(pageParam, qw);
        // 3. 返回分页结果
        return new PageData<>(iPage.getRecords(), iPage.getTotal());
    }

    @Override
    public List<StockSumPo> sumStockExport(Map<String, Object> params) {
        //获取查询参数
        String spuNo = params.get("spuNo").toString();
        String SpuName = params.get("spuName").toString();
        String equipType = params.get("equipType").toString();
        String drawNo = params.get("drawNo").toString();
        QueryWrapper<StockSumPo> qw = new QueryWrapper<>();
        qw.like(StringUtils.isNotBlank(spuNo), "spu_no", spuNo);
        qw.like(StringUtils.isNotBlank(SpuName), "spu_name", SpuName);
        qw.like(StringUtils.isNotBlank(equipType), "equip_type", equipType);
        qw.like(StringUtils.isNotBlank(drawNo), "draw_no", drawNo);
        return baseDao.selectSumStockBySpuNo(qw);
    }

    @Override
    public PageData<StockAggregatedPo> pageByZoneNo(Map<String, Object> params) {
        // 1. 解析分页参数
        int pageNum = Integer.parseInt(params.get("page").toString());
        int pageSize = Integer.parseInt(params.get("limit").toString());
        Page<StockAggregatedPo> pageParam = new Page<>(pageNum, pageSize);

        // 2. 构造分页对象,执行分页查询（调用新增的DAO方法）
        IPage<StockAggregatedPo> iPage = baseDao.selectOrderByZoneNo(pageParam, getWrapperBySpuNo(params));

        // 3. 返回分页结果
        return new PageData<>(iPage.getRecords(), iPage.getTotal());
    }

    @Override
    public List<StockAggregatedPo> orderBySpuNo(Map<String, Object> params) {
        return baseDao.selectOrderBySpuNo(getWrapperBySpuNo(params));
    }

    @Override
    public List<StockAggregatedPo> orderByZoneNo(Map<String, Object> params) {
        return baseDao.selectOrderByZoneNo(getWrapperBySpuNo(params));
    }

    public QueryWrapper<StockAggregatedPo> getWrapperBySpuNo(Map<String, Object> params) {
        //查询条件
        String spuNo = (String) params.get("spuNo");
        String spuName = (String) params.get("spuName");
        String zoneNo = (String) params.get("zoneNo");

        QueryWrapper<StockAggregatedPo> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(zoneNo), "zone_no", zoneNo);
        wrapper.like(StringUtils.isNotBlank(spuNo), "spu_no", spuNo);
        wrapper.like(StringUtils.isNotBlank(spuName), "spu_name", spuName);

        return wrapper;
    }

    private StockEntity convertToEntity(ImportStockExcel excel) {
        StockEntity stock = new StockEntity();
        BeanUtils.copyProperties(excel, stock);
//        // 处理特殊字段（如日期格式）
//        stock.setCreateDate(excel.getCreateDate());
//        stock.setUpdateDate(excel.getUpdateDate());
        return stock;
    }
}